home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / comm / revrdist.sit / RevRdist / RevRdist src / TransSkel.c < prev   
Encoding:
C/C++ Source or Header  |  1990-07-26  |  37.1 KB  |  1,544 lines  |  [TEXT/KAHL]

  1. /*
  2.     TransSkel version 2.01 - Transportable application skeleton
  3.     
  4.     TransSkel is public domain and was originally written by:
  5.  
  6.                 Paul DuBois
  7.                 Wisconsin Regional Primate Research Center
  8.                 1220 Capital Court
  9.                 Madison WI  53715-1299  USA
  10.  
  11.     UUCP:        {allegra,uunet}!uwvax!rhesus!dubois
  12.     Internet:    dubois@primate.wisc.edu
  13.             
  14.     Additional changes were made by
  15.         
  16.                 Owen Hartnett
  17.                 OHM Software Company
  18.                 163 Richard Drive
  19.                 Tiverton, RI 02878  USA
  20.             
  21.     UUCP:        {allegra,uunet}!brunix!omh    
  22.     Internet:    omh@cs.brown.edu
  23.     CSNET:        omh@cs.brown.edu.CSNET         
  24.  
  25.     Owen is also responsible for the port to Lightspeed Pascal.
  26.     
  27.     This version of TransSkel written for LightspeedC.  LightspeedC is a
  28.     trademark of:
  29.             THINK Technologies, Inc
  30.             420 Bedford Street  Suite 350
  31.             Lexington, MA  02173  USA
  32.  
  33.     Change history is in TSHistory.c
  34. */
  35.  
  36. /*
  37.     The following symbol controls support for dialogs.
  38.     "#define    supportDialogs" enables support.
  39.     "#undef        supportDialogs" disables support.
  40. */
  41.  
  42. # define    supportDialogs
  43.  
  44.  
  45. # ifdef        supportDialogs
  46. #    include    <DialogMgr.h>
  47. # else
  48. #    include    <WindowMgr.h>
  49. # endif
  50.  
  51. # include    <EventMgr.h>
  52. # include    <MenuMgr.h>
  53.  
  54.  
  55. #include <C_config.h>
  56. #include <TransSkelProto.h>
  57.  
  58. # define    mBarHeight    20    /* menu bar height.  All window sizing
  59.                                code takes this into account */
  60.  
  61.  
  62. /*
  63.     New(TypeName) returns handle to new object, for any TypeName.
  64.     If there is insufficient memory, the result is nil.
  65. */
  66.  
  67. # define    New(x)    (x **) NewHandle ((Size) sizeof (x))
  68.  
  69.  
  70.  
  71. /*
  72.     Window and Menu handler types, constants, variables.
  73.  
  74.     whList and mhList are the lists of window and menu handlers.
  75.     whClobOnRmve and mhClobOnRmve are true if the handler disposal proc
  76.     is to be called when a handler is removed.  They are temporarily set
  77.     false when handlers are installed for windows or menus that already
  78.     have handlers - the old handler is removed WITHOUT calling the
  79.     disposal proc.
  80.  
  81.     Default lower limits on window sizing of 80 pixels both directions is
  82.     sufficient to allow text windows room to draw a grow box and scroll
  83.     bars without having the thumb and arrows overlap.  These values may
  84.     be changed if such a constraint is undesirable with SkelGrowBounds.
  85.     Default upper limits are for the Macintosh, not the Lisa, but are set
  86.     per machine in SkelInit.
  87. */
  88.  
  89. typedef struct WHandler    WHandler;
  90.  
  91. struct WHandler
  92. {
  93.     WindowPtr    whWind;            /* window/dialog to be handled  */
  94.     vProcPtr    whClobber;        /* data structure disposal proc */
  95.     vProcPtr    whMouse;        /* mouse-click handler proc     */
  96.     vProcPtr    whKey;            /* key-click handler proc       */
  97.     vProcPtr    whUpdate;        /* update handler proc          */
  98.     vProcPtr    whActivate;        /* activate event handler proc  */
  99.     vProcPtr    whClose;        /* close "event" handler proc   */
  100.     vProcPtr    whIdle;            /* main loop proc               */
  101. # ifdef    supportDialogs
  102.     vProcPtr    whEvent;        /* event proc                   */
  103. # endif
  104.     Rect        whGrow;            /* limits on window sizing      */
  105.     Boolean        whSized;        /* true = window was resized    */
  106.     Boolean        whFrontOnly;    /* true = idle only when active */
  107.     WHandler    **whNext;        /* next window handler          */
  108. };
  109.  
  110. static WHandler    **whList = nil;
  111. static Boolean    whClobOnRmve = true;
  112. static Rect        growRect = { 80, 80, 512, 342 - mBarHeight };
  113.  
  114. typedef struct MHandler    MHandler;
  115.  
  116. struct MHandler
  117. {
  118.     Integer        mhID;            /* menu id                     */
  119.     vProcPtr    mhSelect;        /* item selection handler proc */
  120.     vProcPtr    mhClobber;        /* menu disposal handler proc  */
  121.     MHandler    **mhNext;        /* next menu handler           */
  122. };
  123.  
  124.  
  125. static MHandler    **mhList = nil;            /* list of menu handlers */
  126. static Boolean    mhClobOnRmve = true;
  127.  
  128.  
  129. /*
  130.     Variables for default Apple menu handler.  appleID is set to 1 if
  131.     SkelApple is called and is the id of the Apple menu, appleAboutProc
  132.     is the procedure to execute if there is an About... item and it's
  133.     chosen from the Apple menu.  If doAbout is true, then the menu
  134.     contains the About... item, otherwise it's just desk accessories.
  135. */
  136.  
  137. static MenuHandle    appleMenu;
  138. static Integer        appleID = 0;
  139. static vProcPtr        appleAboutProc = nil;
  140. static Boolean        doAbout = false;
  141.  
  142.  
  143. /*
  144.     Miscellaneous
  145.  
  146.     screenPort points to the window manager port.
  147.  
  148.     doneFlag determines when SkelMain returns.  It is set by calling
  149.     SkelWhoa(), which is how the host requests a halt.
  150.  
  151.     pBkgnd points to a background procedure, to be run during event
  152.     processing.  Set it with SkelBackground.  If nil, there's no
  153.     procedure.
  154.  
  155.     pEvent points to an event-inspecting hook, to be run whenever an
  156.     event occurs.  Set it with SkelEventHook.  If nil, there's no
  157.     procedure.
  158.  
  159.     eventMask controls the event types requested in the GetNextEvent
  160.     call in SkelMain.
  161.  
  162.     diskInitPt is the location at which the disk initialization dialog
  163.     appears, if an uninitialized disk is inserted.
  164. */
  165.  
  166. static GrafPtr    screenPort;
  167. static Integer    doneFlag = false;
  168. static vProcPtr    pBkgnd = nil;
  169. static Boolean    (*pEvent)() = nil;
  170. static Integer    eventMask = everyEvent;
  171. static Point    diskInitPt = { /* v = */ 120, /* h = */ 100 };
  172.  
  173. static WindowPtr    oldWindow = nil;     
  174. static WHandler        **oldWDHandler = nil;
  175.     
  176.  
  177. # ifdef    supportDialogs
  178.  
  179. /*
  180.     dlogEventMask specifies events that are passed to dialogs.
  181.     Others are ignored.  Standard mask passes, mousedown, keydown,
  182.     autokey, update, activate and null events.  Null events are
  183.     controlled by bit 0 (always forced on).
  184. */
  185.  
  186. static Integer    dlogEventMask = 0x16b;
  187.  
  188. # endif
  189.  
  190.  
  191. /* -------------------------------------------------------------------- */
  192. /*                        Internal (private) Routines                        */
  193. /* -------------------------------------------------------------------- */
  194.  
  195. /* prototypes */
  196. static WHandler **GetWDHandler (WindowPtr theWind);
  197. static WHandler **GetWHandler (WindowPtr theWind);
  198. static WHandler **GetDHandler (DialogPtr theDialog);
  199. static void DoMenuCommand (Longint command);
  200. static void DoAppleItem (Integer item);
  201. static void DoAppleClobber (void);
  202. static void DoMouse (WHandler **h, EventRecord *theEvent);
  203. static void DoKey (WHandler **h, char ch, Integer mods);
  204. static void DoUpdate (WHandler **h);
  205. static void DoActivate (WHandler **h, Boolean active);
  206. static void DoClose (WHandler **h);
  207. static void DoClobber (WHandler **h);
  208. static int  DoDialog (EventRecord *theEvent);
  209. static void TriggerUpdate (WHandler **h, GrafPtr grownPort);
  210. static void DoGrow (WHandler **h, GrafPtr growPort, Point startPt);
  211. static void DoZoom (WHandler **h, GrafPtr zoomPort, short partCode);
  212. static void DoEvent (EventRecord *theEvent);
  213.  
  214.  
  215. /*
  216.     Get handler associated with user or dialog window.
  217.     Return nil if window doesn't belong to any known handler.
  218.     This routine is absolutely fundamental to TransSkel.
  219. */
  220.  
  221.  
  222. static WHandler **GetWDHandler (theWind)
  223. WindowPtr    theWind;
  224. {
  225. register WHandler    **h;
  226.  
  227.     if (theWind == oldWindow) 
  228.         return(oldWDHandler);        /* return handler of cached window */
  229.  
  230.     for (h = whList; h != nil; h = (**h).whNext)
  231.     {
  232.         if ((**h).whWind == theWind)
  233.         {
  234.             oldWindow = theWind;    /* set cached window and handler */
  235.             oldWDHandler = h;
  236.             return (h);
  237.         }
  238.     }
  239.     return (nil);
  240. }
  241.  
  242.  
  243. /*
  244.     Get handler associated with user window.
  245.     Return nil if window doesn't belong to any known handler.
  246.     The order of the two tests is critical:  theWind might be nil.
  247. */
  248.  
  249. static WHandler **GetWHandler (theWind)
  250. WindowPtr    theWind;
  251. {
  252. register WHandler    **h;
  253.  
  254.     if ((h = GetWDHandler (theWind)) != nil
  255.         && ((WindowPeek) theWind)->windowKind != dialogKind)
  256.     {
  257.             return (h);
  258.     }
  259.     return (nil);
  260. }
  261.  
  262.  
  263. # ifdef    supportDialogs
  264.  
  265. /*
  266.     Get handler associated with dialog window.
  267.     Return nil if window doesn't belong to any known handler.
  268.     The order of the two tests is critical:  theDialog might be nil.
  269. */
  270.  
  271. static WHandler **GetDHandler (theDialog)
  272. DialogPtr    theDialog;
  273. {
  274. register WHandler    **h;
  275.  
  276.     if ((h = GetWDHandler (theDialog)) != nil
  277.         && ((WindowPeek) theDialog)->windowKind == dialogKind)
  278.     {
  279.             return (h);
  280.     }
  281.     return (nil);
  282. }
  283.  
  284. # endif
  285.  
  286.  
  287. /*
  288.     General menu-handler.  Just passes selection to the handler's
  289.     select routine.  If the select routine is nil, selecting items from
  290.     the menu is a nop.
  291. */
  292.  
  293. static void
  294. DoMenuCommand (command)
  295. Longint        command;
  296. {
  297. register Integer    menu;
  298. register Integer    item;
  299. register MHandler    **mh;
  300. register vProcPtr    p;
  301.  
  302.     menu = HiWord (command);
  303.     item = LoWord (command);
  304.     for (mh = mhList; mh != nil; mh = (**mh).mhNext)
  305.     {
  306.         if ((menu == (**mh).mhID) && ((p = (**mh).mhSelect) != nil))
  307.         {
  308.             (*p) (item);
  309.             break;
  310.         }
  311.     }
  312.     HiliteMenu (0);        /* command done, turn off menu hiliting */
  313. }
  314.  
  315.  
  316. /*
  317.     Apple menu handler
  318.     
  319.     DoAppleItem:  If the first item was chosen, and there's an "About..."
  320.     item, call the procedure associated with it (if not nil).  If there
  321.     is no "About..." item or the item was not the first one, then open
  322.     the associated desk accessory.  The port is saved and restored
  323.     because OpenDeskAcc does not always preserve it correctly.
  324.     
  325.     DoAppleClobber disposes of the Apple menu.
  326. */
  327.  
  328.  
  329. static void
  330. DoAppleItem (item)
  331. Integer    item;
  332. {
  333. GrafPtr    curPort;
  334. Str255    str;
  335. Handle    h;
  336.  
  337.     if (doAbout && item == 1)
  338.     {
  339.         if (appleAboutProc != nil)
  340.             (*appleAboutProc) ();
  341.     }
  342.     else
  343.     {
  344.         GetPort (&curPort);
  345.         GetItem (appleMenu, item, str);        /* get DA name */
  346.         SetResLoad (false);
  347.         h = GetNamedResource ('DRVR', str);
  348.         SetResLoad (true);
  349.         if (h != nil)
  350.         {
  351.             ResrvMem (SizeResource (h) + 0x1000);
  352.             (void) OpenDeskAcc (str);            /* open it */
  353.         }
  354.         SetPort (curPort);
  355.     }
  356. }
  357.  
  358. static void
  359. DoAppleClobber ()
  360. { DisposeMenu (appleMenu); }
  361.  
  362.  
  363. /* -------------------------------------------------------------------- */
  364. /*                        Window-handler routing routines                    */
  365. /*                                                                        */
  366. /*    See manual for discussion of port-setting behavior.  In general,    */
  367. /*    the current port is made to associate with the active window.        */
  368. /*    This is done in DoActivate for non-dialog windows, in DoDialog        */
  369. /*    for dialog windows.                                                    */
  370. /* -------------------------------------------------------------------- */
  371.  
  372.  
  373. /*
  374.     Pass local mouse coordinates, click time, and the modifiers flag
  375.     word to the handler.  Should not be necessary to set the port, as
  376.     the click is passed to the active window's handler.
  377. */
  378.  
  379. static void
  380. DoMouse (h, theEvent)
  381. WHandler    **h;
  382. EventRecord    *theEvent;
  383. {
  384. register vProcPtr    p;
  385. Point                thePt;
  386.  
  387.     if (h != nil)
  388.     {
  389.         if ((p = (**h).whMouse) != nil)
  390.         {
  391.             thePt = theEvent->where;    /* make local copy */
  392.             GlobalToLocal (&thePt);
  393.             (*p) (thePt, theEvent->when, theEvent->modifiers);
  394.         }
  395.     }
  396. }
  397.  
  398.  
  399. /*
  400.     Pass the character and the modifiers flag word to the handler.
  401.     Should not be necessary to set the port, as the click is passed
  402.     to the active window's handler.
  403. */
  404.  
  405. static void
  406. DoKey (h, ch, mods)
  407. WHandler    **h;
  408. char        ch;
  409. Integer        mods;
  410. {
  411. register vProcPtr    p;
  412.  
  413.     if (h != nil)
  414.     {
  415.         if ((p = (**h).whKey) != nil)
  416.             (*p) (ch, mods);
  417.     }
  418. }
  419.  
  420.  
  421. /*
  422.     Call the window updating procedure, passing to it an indicator whether
  423.     the window has been resized or not.  Then clear the flag, assuming
  424.     the update proc took whatever action was necessary to respond to
  425.     resizing.
  426.  
  427.     If the handler doesn't have any update proc, the Begin/EndUpdate
  428.     stuff is still done, to clear the update region.  Otherwise the
  429.     Window Manager will keep generating update events for the window,
  430.     stalling updates of other windows.
  431.  
  432.     Make sure to save and restore the port, as it's not always the
  433.     active window that is updated.
  434. */
  435.  
  436. static void
  437. DoUpdate (h)
  438. WHandler    **h;
  439. {
  440. register WHandler    **rh;
  441. register vProcPtr    p;
  442. register GrafPtr    updPort;
  443. GrafPtr                tmpPort;
  444.  
  445.     if ((rh = h) != nil)
  446.     {
  447.         GetPort (&tmpPort);
  448.         SetPort (updPort = (**rh).whWind);
  449.         BeginUpdate (updPort);
  450.         if ((p = (**rh).whUpdate) != nil)
  451.         {
  452.             (*p) ((**rh).whSized);
  453.             (**rh).whSized = false;
  454.         }
  455.         EndUpdate (updPort);
  456.         SetPort (tmpPort);
  457.     }
  458. }
  459.  
  460.  
  461. /*
  462.     Pass activate/deactivate notification to handler.  On activate,
  463.     set the port to the window coming active.  Normally this is done by
  464.     the user clicking in a window.
  465.  
  466.     *** BUT ***
  467.     Under certain conditions, a deactivate may be generated for a window
  468.     that has not had the port set to it by a preceding activate.  If an
  469.     application puts up window A, then window B in front of A, then
  470.     starts processing events, the first events will be a deactivate for A
  471.     and an activate for B.  Since it therefore can't be assumed the port
  472.     was set to A by an activate, the port needs to be set for deactivates
  473.     as well.
  474.  
  475.     This matters not a whit for the more usual cases that occur.  If a
  476.     deactivate for one window is followed by an activate for another, the
  477.     port will still be switched properly to the newly active window.  If
  478.     no activate follows the deactivate, the deactivated window is the last
  479.     one, and it doesn't matter what the port ends up set to, anyway.
  480. */
  481.  
  482. static void
  483. DoActivate (h, active)
  484. WHandler    **h;
  485. Boolean        active;
  486. {
  487. register vProcPtr    p;
  488.  
  489.     if (h != nil)
  490.     {
  491.         SetPort ((**h).whWind);
  492.         if ((p = (**h).whActivate) != nil)
  493.             (*p) (active);
  494.     }
  495. }
  496.  
  497.  
  498. /*
  499.     Execute a window handler's close box proc.  The close proc for
  500.     handlers for temp windows that want to remove themselves when the
  501.     window is closed can call SkelRmveWind to dispose of the window
  502.     and remove the handler from the window handler list.  Thus, windows
  503.     may be dynamically created and destroyed without filling up the
  504.     handler list with a bunch of invalid handlers.
  505.     
  506.     If the handler doesn't have a close proc, just hide the window.
  507.     The host should provide some way of reopening the window (perhaps
  508.     a menu selection).  Otherwise the window will be lost from user
  509.     control if it is hidden, since it won't receive user-initiated
  510.     events.
  511.  
  512.     This is called both for regular and dialog windows.
  513.  
  514.     Since the close box of only the active window may be clicked, it
  515.     is not necessary to set the port.
  516. */
  517.  
  518. static void
  519. DoClose (h)
  520. WHandler    **h;
  521. {
  522. register WHandler    **rh;
  523. register vProcPtr    p;
  524.  
  525.     if ((rh = h) != nil)
  526.     {
  527.         if ((p = (**rh).whClose) != nil)
  528.             (*p) ();
  529.         else
  530.             HideWindow ((**rh).whWind);
  531.     }
  532. }
  533.  
  534.  
  535. /*
  536.     Execute a window handler's clobber proc.  This is called both
  537.     for regular and dialog windows.
  538.  
  539.     Must save, set and restore port, since any window (not just active
  540.     one) may be clobbered at any time.
  541.  
  542.     Don't need to check whether handler is nil, as in other handler
  543.     procedures, since this is only called by SkelRmveWind with a
  544.     known-valid handler.
  545. */
  546.  
  547. static void
  548. DoClobber (h)
  549. WHandler    **h;
  550. {
  551. register vProcPtr    p;
  552. GrafPtr                tmpPort;
  553.  
  554.     GetPort (&tmpPort);
  555.     SetPort ((**h).whWind);
  556.     if ((p = (**h).whClobber) != nil)
  557.         (*p) ();
  558.     SetPort (tmpPort);
  559. }
  560.  
  561.  
  562. # ifdef    supportDialogs
  563.  
  564. /* -------------------------------------------------------------------- */
  565. /*                            Dialog-handling routines                    */
  566. /* -------------------------------------------------------------------- */
  567.  
  568.  
  569. /*
  570.     Handle event if it's for a (modeless) dialog.  The event must be one
  571.     of those that is passed to dialogs according to dlogEventMask.
  572.     This mask can be set so that disk-inserts, for instance, don't
  573.     get eaten up.
  574.  
  575.     Examine event and set port if dialog window is coming active (for
  576.     normal windows, DoActivate sets the port; there's no such thing
  577.     for dialogs, so it's done here.)  When this is done, the trio
  578.     of GetPort/SetPort/SetPort calls commented out below doesn't appear
  579.     to be necessary any longer.  If you want to be cautious, it doesn't
  580.     hurt to uncomment them...
  581. */
  582.  
  583. static DoDialog (theEvent)
  584. register EventRecord    *theEvent;
  585. {
  586. register WHandler    **dh;
  587. DialogPtr            theDialog;
  588. register Integer    what;
  589. Integer                item;
  590. GrafPtr                tmpPort;
  591. WindowPeek            w;
  592.  
  593. /*
  594.     handle command keys before they get to IsDialogEvent
  595. */
  596.  
  597.     what = theEvent->what;
  598.     if((what == keyDown || what == autoKey) && (theEvent->modifiers & cmdKey))
  599.     {
  600.            DoMenuCommand (MenuKey (theEvent->message & charCodeMask));
  601.            return (true);
  602.     }
  603.     
  604.     if (((1 << what) & dlogEventMask) && IsDialogEvent (theEvent))
  605.     {
  606.         /* ugly programming award semi-finalist follows */
  607.         if (theEvent->what == activateEvt            /* if activate */
  608.             && (theEvent->modifiers & activeFlag)    /* and coming active */
  609.             && (w=(WindowPeek) theEvent->message)->windowKind
  610.                     == dialogKind)
  611.         {
  612.             SetPort ((GrafPtr) w);
  613.         }
  614.         if ((DialogSelect (theEvent, &theDialog, &item)
  615.             || theEvent->what == activateEvt)
  616.            && (dh = GetDHandler (theDialog)) != nil
  617.            && (**dh).whEvent != nil)
  618.         {
  619.             /*GetPort (&tmpPort);*/
  620.             /*SetPort (theDialog);*/
  621.             (*(**dh).whEvent) (item, theEvent);
  622.             /*SetPort (tmpPort);*/
  623.         }
  624.         return (true);
  625.     }
  626.     return (false);
  627. }
  628.  
  629. # endif
  630.  
  631.  
  632. /* -------------------------------------------------------------------- */
  633. /*                            Event-handling routines                        */
  634. /* -------------------------------------------------------------------- */
  635.  
  636.  
  637. /*
  638.     Have either zoomed a window or sized it manually.  Invalidate
  639.     it to force an update and set the 'resized' flag in the window
  640.     handler true.  The port is assumed to be set to the port that changed
  641.     size.
  642. */
  643.  
  644. static void
  645. TriggerUpdate (h, grownPort)
  646. WHandler    **h;
  647. GrafPtr        grownPort;
  648. {
  649.     InvalRect (&grownPort->portRect);
  650.     if (h != nil)
  651.         (**h).whSized = true;
  652. }
  653.  
  654.  
  655. /*
  656.     Size a window.  If the window has a handler, use the grow limits
  657.     in the handler record, otherwise use the defaults.
  658.  
  659.     The portRect is invalidated to force an update event.  The handler's
  660.     update procedure should check the parameter passed to it to check
  661.     whether the window has changed size, if it needs to adjust itself to
  662.     the new size.  THIS IS A CONVENTION.  Update procs must notice grow
  663.     "events", there is no procedure specifically for such events.
  664.     
  665.     The clipping rectangle is not reset.  If the host application
  666.     keeps the clipping set equal to the portRect or something similar,
  667.     then it will have to arrange to treat window growing with more
  668.     care.
  669.  
  670.     Since the grow region of only the active window may be clicked,
  671.     it should not be necessary to set the port.
  672. */
  673.  
  674. static void
  675. DoGrow (h, growPort, startPt)
  676. WHandler    **h;
  677. GrafPtr        growPort;
  678. Point        startPt;
  679. {
  680. Rect                r;
  681. register Longint    growRes;
  682.  
  683.     if (h != nil)
  684.         r = (**h).whGrow;
  685.     else
  686.         r = growRect;    /* use default */
  687.  
  688.     /* grow result non-zero if size change    */
  689.  
  690.     if (growRes = GrowWindow (growPort, startPt, &r))
  691.     {
  692.         SizeWindow (growPort, LoWord (growRes), HiWord (growRes), false);
  693.         TriggerUpdate (h, growPort);
  694.     }
  695. }
  696.  
  697.  
  698. /*
  699.     Zoom the current window.  Very similar to DoGrow
  700.  
  701.     Since the zoombox of only the active window may be clicked,
  702.     it should not be necessary to set the port.
  703. */
  704.  
  705. static void
  706. DoZoom (h, zoomPort, partCode)
  707. register WHandler    **h;
  708. GrafPtr                zoomPort;
  709. short                partCode;
  710. {
  711.     ZoomWindow (zoomPort, partCode, 0);
  712.     TriggerUpdate (h, zoomPort);
  713. }
  714.  
  715.  
  716. /*
  717.     General event handler
  718. */
  719.  
  720. static void
  721. DoEvent (theEvent)
  722. register EventRecord    *theEvent;
  723.  
  724. {
  725. Point                evtPt;
  726. GrafPtr                evtPort;
  727. register Integer    evtPart;
  728. register char        evtChar;
  729. register Integer    evtMods;
  730. register Longint    evtMsge;
  731. register WHandler    **h;
  732. Rect                r;
  733.  
  734. # ifdef    supportDialogs
  735.  
  736.     if(DoDialog (theEvent))
  737.         return;
  738.  
  739. # endif
  740.  
  741.     evtPt = theEvent->where;
  742.     evtMods = theEvent->modifiers;
  743.     evtMsge = theEvent->message;
  744.  
  745.     switch (theEvent->what)
  746.     {
  747.  
  748.         /*case nullEvent:
  749.             break;*/
  750. /*
  751.     Mouse click.  Get the window that the click occurred in, and the
  752.     part of the window.  GetWDHandler is called here, not GetWHandler, since
  753.     we need the handler for a window which might turn out to be a dialog
  754.     window, e.g., if the click is in a close box.
  755. */
  756.         case mouseDown:
  757.         {
  758.             evtPart = FindWindow (evtPt, &evtPort);
  759.             h = GetWDHandler (evtPort);
  760.  
  761.             switch (evtPart)
  762.             {
  763. /*
  764.     Click in a desk accessory window.  Pass back to the system.
  765. */
  766.                 case inSysWindow:
  767.                 {
  768.                     SystemClick (theEvent, evtPort);
  769.                     break;
  770.                 }
  771. /*
  772.     Click in menu bar.  Track the mouse and execute selected command,
  773.     if any.
  774. */
  775.                 case inMenuBar:
  776.                 {
  777.                     DoMenuCommand (MenuSelect (evtPt));
  778.                     break;
  779.                 }
  780. /*
  781.     Click in grow box.  Resize window.
  782. */
  783.                 case inGrow:
  784.                 {
  785.                     DoGrow (h, evtPort, evtPt);
  786.                     break;
  787.                 }
  788. /*
  789.     Click in title bar.  Drag the window around.  Leave at least
  790.     4 pixels visible in both directions.
  791.     Bug fix:  The window is selected first to make sure it's at least
  792.     activated (unless the command key is down-see Inside Macintosh).
  793.     DragWindow seems to call StillDown first, so that clicks in drag
  794.     regions while machine is busy don't otherwise bring window to front if
  795.     the mouse is already up by the time DragWindow is called.
  796. */
  797.                 case inDrag:
  798.                 {
  799.                     if (evtPort != FrontWindow () && (evtMods & cmdKey) == 0)
  800.                         SelectWindow (evtPort);
  801.                     r = screenPort->portRect;
  802.                     r.top += mBarHeight;            /* skip down past menu bar */
  803.                     InsetRect (&r, 4, 4);
  804.                     DragWindow (evtPort, evtPt, &r);
  805.                     break;
  806.                 }
  807. /*
  808.     Click in close box.  Call the close proc if the window has one.
  809. */
  810.                 case inGoAway:
  811.                 {
  812.                     if (TrackGoAway (evtPort, evtPt))
  813.                         DoClose (h);
  814.                     break;
  815.                 }
  816.  
  817. /*
  818.     Click in zoom box.  Track the click and then zoom the window if
  819.     necessary
  820. */
  821.                 case inZoomIn:
  822.                 case inZoomOut:
  823.                 {
  824.                     if (TrackBox (evtPort, evtPt, evtPart))
  825.                         DoZoom (h, evtPort, evtPart);
  826.                     break;
  827.                 }
  828. /*
  829.     Click in content region.  If the window wasn't frontmost (active),
  830.     just select it, otherwise pass the click to the window's mouse
  831.     click handler.
  832. */
  833.                 case inContent:
  834.                 {
  835.                     if (evtPort != FrontWindow ())
  836.                         SelectWindow (evtPort);
  837.                     else
  838.                         DoMouse (h, theEvent);
  839.                     break;
  840.                 }
  841.  
  842.             }
  843.             break;    /* mouseDown */
  844.         }
  845. /*
  846.     Key event.  If the command key was down, process as menu item
  847.     selection, otherwise pass the character and the modifiers flags
  848.     to the active window's key handler.
  849.  
  850.     If dialogs are supported, there's no check for command-key
  851.     equivalents, since that would have been checked in DoDialog.
  852. */
  853.         case keyDown:
  854.         case autoKey:
  855.         {
  856.             evtChar = evtMsge & charCodeMask;
  857.  
  858. # ifndef    supportDialogs
  859.  
  860.             if (evtMods & cmdKey)        /* try menu equivalent */
  861.             {
  862.                 DoMenuCommand (MenuKey (evtChar));
  863.                 break;
  864.             }
  865.  
  866. # endif
  867.  
  868.             DoKey (GetWHandler (FrontWindow ()), evtChar, evtMods);
  869.             break;
  870.         }
  871. /*
  872.     Update a window.
  873. */
  874.         case updateEvt:
  875.         {
  876.             DoUpdate (GetWHandler ((WindowPtr) evtMsge));
  877.             break;
  878.         }
  879. /*
  880.     Activate or deactivate a window.
  881. */
  882.         case activateEvt:
  883.         {
  884.             DoActivate (GetWHandler ((WindowPtr) evtMsge),
  885.                         ((evtMods & activeFlag) != 0));
  886.             break;
  887.         }
  888. /*
  889.     handle inserts of uninitialized disks
  890. */
  891.         case diskEvt:
  892.         {
  893.             if (HiWord (evtMsge) != noErr)
  894.             {
  895.                 DILoad ();
  896.                 (void) DIBadMount (diskInitPt, evtMsge);
  897.                 DIUnload ();
  898.             }
  899.             break;
  900.         }
  901.     }
  902. }
  903.  
  904.  
  905. /* -------------------------------------------------------------------- */
  906. /*                        Interface (public) Routines                        */
  907. /* -------------------------------------------------------------------- */
  908.  
  909.  
  910. /*
  911.     Initialize the various Macintosh Managers.
  912.     Set default upper limits on window sizing.
  913.     FlushEvents does NOT toss disk insert events, so that disks
  914.     inserted while the application is starting up don't result
  915.     in dead drives.
  916.  
  917.     noMasters is the number of times to call MoreMasters.  gzProc is
  918.     the address of a grow zone procedure to call if memory allocation
  919.     problems occur.  Pass nil if none to be used.
  920. */
  921.  
  922. void
  923. SkelInit (noMasters, gzProc)
  924. int        noMasters;
  925. lProcPtr    gzProc;
  926. {
  927.     while (noMasters-- > 0)
  928.         MoreMasters ();
  929.  
  930.     if (gzProc != nil)
  931.         SetGrowZone (gzProc);
  932.  
  933.     MaxApplZone ();
  934.     FlushEvents (everyEvent - diskMask, 0 );
  935.     InitGraf (&thePort);
  936.     InitFonts ();
  937.     InitWindows ();
  938.     InitMenus ();
  939.     TEInit ();
  940.     InitDialogs (nil);        /* no restart proc */
  941.     InitCursor ();
  942. /*
  943.     Set upper limits of window sizing to machine screen size.  Allow
  944.     for the menu bar.
  945. */
  946.     GetWMgrPort (&screenPort);
  947.     growRect.right = screenPort->portRect.right;
  948.     growRect.bottom = screenPort->portRect.bottom - mBarHeight;
  949. }
  950.  
  951.  
  952. /*
  953.     Main loop.
  954.  
  955.     Task care of DA's with SystemTask.
  956.     Run background task if there is one.
  957.     If there is an event, check for an event hook.  If there isn't
  958.     one defined, or if there is but it returns false, call the
  959.     general event handler.  (Hook returns true if TransSkel should
  960.     ignore the event.)
  961.     If no event, call the "no-event" handler for the front window and for
  962.     any other windows with idle procedures that are always supposed
  963.     to run.  This is done in such a way that it is safe for idle procs
  964.     to remove the handler for their own window if they want (unlikely,
  965.     but...)  This loop doesn't check whether the window is really
  966.     a dialog window or not, but it doesn't have to, because such
  967.     things always have a nil idle proc.
  968.     
  969.     doneFlag is reset upon exit.  This allows SkelMain to be called
  970.     repeatedly, or recursively.
  971.  
  972.     Null events are examined (in SkelMain) and passed to the event
  973.     handler.  This is necessary to make sure, if dialogs are supported,
  974.     that DialogSelect gets called repeatedly, or the caret won't blink
  975.     if a dialog has any editText items.
  976.  
  977.     Null events are not passed to any event-inspecting hook that may
  978.     be installed.
  979. */
  980.  
  981. void
  982. SkelMain ()
  983. {
  984. EventRecord            theEvent;
  985. register WHandler    **wh, **wh2;
  986. register WindowPtr    w;
  987. Boolean                haveEvent;
  988. GrafPtr                tmpPort;
  989. register vProcPtr    p;
  990.  
  991.     while (!doneFlag)
  992.     {    
  993.         SystemTask ();
  994.         if (pBkgnd != nil)
  995.             (*pBkgnd) ();
  996.  
  997. /*
  998.     Now watch carefully.  GetNextEvent calls SystemEvent to handle some
  999.     DA events, and returns false if the event was handled.  However, in
  1000.     such cases the event record will still have the event that occurred,
  1001.     *not* a null event, as you might reasonably expect.  So it's not
  1002.     enough to look at haveEvent.
  1003.  
  1004.     Previous versions figured (wrongly) that haveEvent==false meant a null
  1005.     event had occurred, and passed it through to DoEvent and DoDialog, so
  1006.     that caret-blinking in dialog TextEdit items would occur.  But cmd-key
  1007.     equivalents while DA windows were in front, in particular, allowed
  1008.     already-processed DA events to get into DoEvent (because haveEvent
  1009.     was false), and they got handled twice because when the event record
  1010.     was examined, lo and behold, it had a cmd-key event!  So now this
  1011.     logic is used:
  1012.  
  1013.     If have a real event, and there's no event hook or there is but it
  1014.     doesn't handle the event, OR if the "non-event" is a true nullEvent,
  1015.     then process it.
  1016. */
  1017.             
  1018.         haveEvent = GetNextEvent (eventMask, &theEvent);
  1019.  
  1020.         if ((haveEvent && (pEvent == nil || (*pEvent)(&theEvent) == false))
  1021.                 || theEvent.what == nullEvent)
  1022.             DoEvent(&theEvent);
  1023.  
  1024. /*
  1025.     Run applicable idle procs.  Make sure to save and restore the port,
  1026.     since idle procs for the non-active window may be run.
  1027. */
  1028.  
  1029.         if (!haveEvent)
  1030.         {
  1031.             GetPort (&tmpPort);
  1032.             for (wh = whList; wh != nil; wh = wh2)
  1033.             {
  1034.                 wh2 = (**wh).whNext;
  1035.                 w = (**wh).whWind;
  1036.                 if ( (w == FrontWindow () || !(**wh).whFrontOnly ) )
  1037.                 {
  1038.                     SystemTask ();
  1039.                     if ((p = (**wh).whIdle) != nil)
  1040.                     {
  1041.                         SetPort (w);
  1042.                         (*p) ();
  1043.                     }
  1044.                 }
  1045.             }
  1046.             SetPort (tmpPort);
  1047.         }
  1048.     }
  1049.     doneFlag = false;
  1050. }
  1051.  
  1052.  
  1053. /*
  1054.     Tell SkelMain to stop
  1055. */
  1056.  
  1057. void
  1058. SkelWhoa () {
  1059.     doneFlag = true;
  1060. }
  1061.  
  1062.  
  1063. /*
  1064.     Clobber all the menu, window and dialog handlers
  1065. */
  1066.  
  1067. void
  1068. SkelClobber ()
  1069. {
  1070.     while (whList != nil)
  1071.         SkelRmveWind ((**whList).whWind);
  1072.  
  1073.     while (mhList != nil)
  1074.         SkelRmveMenu (GetMHandle((**mhList).mhID));
  1075. }
  1076.  
  1077.  
  1078. /* -------------------------------------------------------------------- */
  1079. /*                        Menu-handler interface routines                    */
  1080. /* -------------------------------------------------------------------- */
  1081.  
  1082.  
  1083. /*
  1084.     Install handler for a menu.  Remove any previous handler for it.
  1085.     Pass the following parameters:
  1086.  
  1087.     theMenu    Handle to the menu to be handled.  Must be created by host.
  1088.     pSelect    Proc that handles selection of items from menu.  If this is
  1089.             nil, the menu is installed, but nothing happens when items
  1090.             are selected from it.
  1091.     pClobber Proc for disposal of handler's data structures.  Usually
  1092.             nil for menus that remain in menu bar until program
  1093.             termination.
  1094.     
  1095.     The menu is installed, and also drawn in the menu bar if drawBar true.
  1096.     
  1097.     Return 0 if no handler could be allocated, non-zero if successful.
  1098. */
  1099.  
  1100. SkelMenu (theMenu, pSelect, pClobber, drawBar)
  1101. MenuHandle    theMenu;
  1102. vProcPtr    pSelect;
  1103. vProcPtr    pClobber;
  1104. Boolean        drawBar;
  1105. {
  1106. register MHandler    **mh;
  1107.  
  1108.     mhClobOnRmve = false;
  1109.     SkelRmveMenu (theMenu);
  1110.     mhClobOnRmve = true;
  1111.  
  1112.     if ((mh = New (MHandler)) != nil)
  1113.     {
  1114.         (**mh).mhNext = mhList;
  1115.         mhList = mh;
  1116.         (**mh).mhID = (**theMenu).menuID;    /* get menu id number */
  1117.         (**mh).mhSelect = pSelect;            /* install selection handler */
  1118.         (**mh).mhClobber = pClobber;        /* install disposal handler */
  1119.         InsertMenu (theMenu, 0);            /* put menu at end of menu bar */
  1120.     }
  1121.     if (drawBar)
  1122.         DrawMenuBar ();
  1123.     return (mh != nil);
  1124. }
  1125.  
  1126.  
  1127. /*
  1128.     Remove a menu handler.  This calls the handler's disposal routine
  1129.     and then takes the handler out of the handler list and disposes
  1130.     of it.
  1131.  
  1132.     Note that the menu MUST be deleted from the menu bar before calling
  1133.     the clobber proc, because the menu bar will end up filled with
  1134.     garbage if the menu was allocated with NewMenu (see discussion of
  1135.     DisposeMenu in Menu Manager section of Inside Macintosh).
  1136. */
  1137.  
  1138. void
  1139. SkelRmveMenu (theMenu)
  1140. MenuHandle    theMenu;
  1141. {
  1142. register Integer    mID;
  1143. register MHandler    **h, **h2;
  1144. register vProcPtr    p;
  1145.  
  1146.     mID = (**theMenu).menuID;
  1147.     if (mhList != nil)                /* if list empty, ignore */
  1148.     {
  1149.         if ((**mhList).mhID == mID)    /* is it the first element? */
  1150.         {
  1151.             h2 = mhList;
  1152.             mhList = (**mhList).mhNext;
  1153.         }
  1154.         else
  1155.         {
  1156.             for (h = mhList; h != nil; h = h2)
  1157.             {
  1158.                 h2 = (**h).mhNext;
  1159.                 if (h2 == nil)
  1160.                     return;                        /* menu not in list! */
  1161.                 if ((**h2).mhID == mID)            /* found it */
  1162.                 {
  1163.                     (**h).mhNext = (**h2).mhNext;
  1164.                     break;
  1165.                 }
  1166.             }
  1167.         }
  1168.         DeleteMenu (mID);
  1169.         DrawMenuBar ();
  1170.         if (mhClobOnRmve && (p = (**h2).mhClobber) != nil)
  1171.             (*p) (theMenu);                /* call disposal routine */
  1172.         DisposHandle ((Handle)h2);        /* get rid of handler record */
  1173.     }
  1174. }
  1175.  
  1176.  
  1177. /*
  1178.     Install a handler for the Apple menu.
  1179.     
  1180.     SkelApple is called if TransSkel is supposed to handle the apple
  1181.     menu itself.  aboutTitle is the title of the first item.  If nil,
  1182.     then only desk accessories are put into the menu.  If not nil, then
  1183.     the title is entered as the first item, followed by a gray line,
  1184.     then the desk accessories.
  1185.  
  1186.     SkelApple does not cause the menubar to be drawn, so if the Apple
  1187.     menu is the only menu, DrawMenuBar must be called afterward.
  1188.  
  1189.     No value is returned, unlike SkelMenu.  It is assumed that SkelApple
  1190.     will be called so early in the application that the call the SkelMenu
  1191.     is virtually certain to succeed.  If it doesn't, there's probably
  1192.     little hope for the application anyway.
  1193. */
  1194.  
  1195. void
  1196. SkelApple (aboutTitle, aboutProc)
  1197. StringPtr    aboutTitle;
  1198. vProcPtr    aboutProc;
  1199. {
  1200.     appleID = 1;
  1201.     appleMenu = NewMenu (appleID, "\p\024");    /* 024 = apple character */
  1202.     if (aboutTitle != nil)
  1203.     {
  1204.         doAbout = true;
  1205.         AppendMenu (appleMenu, aboutTitle);    /* add About... item title */
  1206.         AppendMenu (appleMenu, "\p(-");        /* add gray line */
  1207.         appleAboutProc = aboutProc;
  1208.     }
  1209.     AddResMenu (appleMenu, 'DRVR');        /* add desk accessories */
  1210.     (void) SkelMenu (appleMenu, DoAppleItem, DoAppleClobber, false);
  1211. }
  1212.  
  1213.  
  1214. /* -------------------------------------------------------------------- */
  1215. /*                    Window-handler interface routines                    */
  1216. /* -------------------------------------------------------------------- */
  1217.  
  1218.  
  1219. /*
  1220.     Install handler for a window and set current port to it.  Remove
  1221.     any previous handler for it.  Pass the following parameters:
  1222.  
  1223.     theWind    Pointer to the window to be handled.  Must be created by host.
  1224.     pMouse    Proc to handle mouse clicks in window.  The proc will be
  1225.             passed the point (in local coordinates), the time of the
  1226.             click, and the modifier flags word.
  1227.     pKey    Proc to handle key clicks in window.  The proc will be passed
  1228.             the character and the modifier flags word.
  1229.     pUpdate    Proc for updating window.  TransSkel brackets calls to update
  1230.             procs with calls to BeginUpdate and EndUpdate, so the visRgn
  1231.             is set up correctly.  A flag is passed indicating whether the
  1232.             window was resized or not.  BY CONVENTION, the entire portRect
  1233.             is invalidated when the window is resized.  That way, the
  1234.             handler's update proc can redraw the entire content region
  1235.             without interference from BeginUpdate/EndUpdate.  The flag
  1236.             is set to false after the update proc is called; the
  1237.             assumption is made that it will notice the resizing and
  1238.             respond appropriately.
  1239.     pActivate Proc to execute when window is activated or deactivated.
  1240.             A boolean is passed to it which is true if the window is
  1241.             coming active, false if it's going inactive.
  1242.     pClose    Proc to execute when mouse clicked in close box.  Useful
  1243.             mainly to temp window handlers that want to know when to
  1244.             self-destruct (with SkelRmveWind).
  1245.     pClobber Proc for disposal of handler's data structures
  1246.     pIdle    Proc to execute when no events are pending.
  1247.     frontOnly True if pIdle should execute on no events only when
  1248.             theWind is frontmost, false if executes all the time.  Note
  1249.             that if it always goes, everything else may be slowed down!
  1250.  
  1251.     If a particular procedure is not needed (e.g., key events are
  1252.     not processed by a handler), pass nil in place of the appropriate
  1253.     procedure address.
  1254.     
  1255.     Return zero if no handler could be allocated, non-zero if successful.
  1256.     If zero is returned, the port will not have changed.
  1257. */
  1258.  
  1259. SkelWindow (theWind, pMouse, pKey, pUpdate, pActivate, pClose,
  1260.                 pClobber, pIdle, frontOnly)
  1261.  
  1262. WindowPtr    theWind;
  1263. vProcPtr    pMouse, pKey, pUpdate, pActivate, pClose, pClobber, pIdle;
  1264. Boolean        frontOnly;
  1265. {
  1266. register WHandler    **hHand, *hPtr;
  1267.  
  1268.     whClobOnRmve = false;
  1269.     SkelRmveWind (theWind);
  1270.     whClobOnRmve = true;
  1271.  
  1272. /*
  1273.     Get new handler, attach to list of handlers.  It is attached to the
  1274.     beginning of the list, which is simpler; the order is presumably
  1275.     irrelevant to the host, anyway.
  1276. */
  1277.  
  1278.     if ((hHand = New (WHandler)) != nil)
  1279.     {
  1280.         (**hHand).whNext = whList;
  1281.         whList = hHand;
  1282.  
  1283. /*
  1284.     Fill in handler fields
  1285. */
  1286.  
  1287.         hPtr = *hHand;
  1288.         hPtr->whWind = theWind;
  1289.         hPtr->whMouse = pMouse;
  1290.         hPtr->whKey = pKey;
  1291.         hPtr->whUpdate = pUpdate;
  1292.         hPtr->whActivate = pActivate;
  1293.         hPtr->whClose = pClose;
  1294.         hPtr->whClobber = pClobber;
  1295.         hPtr->whIdle = pIdle;
  1296.         hPtr->whFrontOnly = frontOnly;
  1297.         hPtr->whSized = false;
  1298.         hPtr->whGrow = growRect;
  1299.         SetPort (theWind);
  1300.     }
  1301.     return (hHand != nil);
  1302. }
  1303.  
  1304.  
  1305. /*
  1306.     Remove a window handler.  This calls the handler's disposal routine
  1307.     and then takes the handler out of the handler list and disposes
  1308.     of it.
  1309.  
  1310.     SkelRmveWind is also called by SkelRmveDlog.
  1311.  
  1312.     Note that if the window cache variable is set to the window whose
  1313.     handler is being clobbered, the variable must be zeroed.
  1314. */
  1315.  
  1316. void
  1317. SkelRmveWind (theWind)
  1318. WindowPtr    theWind;
  1319. {
  1320. register WHandler    **h, **h2;
  1321.  
  1322.     if (theWind == oldWindow)
  1323.         oldWindow = nil;
  1324.  
  1325.     if (whList != nil)        /* if list empty, ignore */
  1326.     {
  1327.         if ((**whList).whWind == theWind)    /* is it the first element? */
  1328.         {
  1329.             h2 = whList;
  1330.             whList = (**whList).whNext;
  1331.         }
  1332.         else
  1333.         {
  1334.             for (h = whList; h != nil; h = h2)
  1335.             {
  1336.                 h2 = (**h).whNext;
  1337.                 if (h2 == nil)
  1338.                     return;                        /* theWind not in list! */
  1339.                 if ((**h2).whWind == theWind)    /* found it */
  1340.                 {
  1341.                     (**h).whNext = (**h2).whNext;
  1342.                     break;
  1343.                 }
  1344.             }
  1345.         }
  1346.         if (whClobOnRmve)
  1347.             DoClobber (h2);        /* call disposal routine */
  1348.         DisposHandle ((Handle)h2);    /* get rid of handler record */
  1349.     }
  1350. }
  1351.  
  1352.  
  1353. # ifdef    supportDialogs
  1354.  
  1355. /* -------------------------------------------------------------------- */
  1356. /*                    Dialog-handler interface routines                    */
  1357. /* -------------------------------------------------------------------- */
  1358.  
  1359.  
  1360. /*
  1361.     Install a handler for a modeless dialog window and set the port
  1362.     to it.  Remove any previous handler for it. SkelDialog calls
  1363.     SkelWindow as a subsidiary to install a window handler, then sets
  1364.     the event procedure on return.
  1365.  
  1366.     Pass the following parameters:
  1367.  
  1368.     theDialog    Pointer to the dialog to be handled.  Must be created
  1369.             by host.
  1370.     pEvent    Event-handling proc for dialog events.
  1371.     pClose    Proc to execute when mouse clicked in close box.  Useful
  1372.             mainly to dialog handlers that want to know when to
  1373.             self-destruct (with SkelRmveDlog).
  1374.     pClobber Proc for disposal of handler's data structures
  1375.  
  1376.     If a particular procedure is not needed, pass nil in place of
  1377.     the appropriate procedure address.
  1378.     
  1379.     Return zero if no handler could be allocated, non-zero if successful.
  1380.     If zero is returned, the port will not have changed.
  1381. */
  1382.  
  1383. SkelDialog (theDialog, pEvent, pClose, pClobber)
  1384. DialogPtr    theDialog;
  1385. vProcPtr    pEvent;
  1386. vProcPtr    pClose;
  1387. vProcPtr    pClobber;
  1388. {
  1389. int        swOk;
  1390.  
  1391.     if (SkelWindow (theDialog, nil, nil, nil, nil, pClose, pClobber, nil, false))
  1392.     {
  1393.         (**GetWDHandler (theDialog)).whEvent = pEvent;
  1394.         return (1);
  1395.     }
  1396.     return (0);
  1397. }
  1398.  
  1399.  
  1400. /*
  1401.     Remove a dialog and its handler
  1402. */
  1403.  
  1404. void
  1405. SkelRmveDlog (theDialog)
  1406. DialogPtr    theDialog;
  1407. {
  1408.     SkelRmveWind (theDialog);
  1409. }
  1410.  
  1411. # endif
  1412.  
  1413.  
  1414. /* -------------------------------------------------------------------- */
  1415. /*                    Miscellaneous interface routines                    */
  1416. /* -------------------------------------------------------------------- */
  1417.  
  1418.  
  1419. /*
  1420.     Override the default sizing limits for a window, or, if theWind
  1421.     is nil, reset the default limits used by SkelWindow.
  1422. */
  1423.  
  1424. void
  1425. SkelGrowBounds (theWind, hLo, vLo, hHi, vHi)
  1426. WindowPtr    theWind;
  1427. Integer            hLo, vLo, hHi, vHi;
  1428. {
  1429. register WHandler    **h;
  1430. Rect                r;
  1431.  
  1432.     if (theWind == nil)
  1433.         SetRect (&growRect, hLo, vLo, hHi, vHi);
  1434.     else if ((h = GetWHandler (theWind)) != nil)
  1435.     {
  1436.         SetRect (&r, hLo, vLo, hHi, vHi);
  1437.         (**h).whGrow = r;
  1438.     }
  1439. }
  1440.  
  1441.  
  1442. /*
  1443.     Set the event mask.
  1444. */
  1445.  
  1446. void
  1447. SkelEventMask (mask)
  1448. Integer        mask;
  1449. {
  1450.     eventMask = mask;
  1451. }
  1452.  
  1453.  
  1454. /*
  1455.     Return the event mask.
  1456. */
  1457.  
  1458. void
  1459. SkelGetEventMask (mask)
  1460. Integer        *mask;
  1461. {
  1462.     *mask = eventMask;
  1463. }
  1464.  
  1465.  
  1466. /*
  1467.     Install a background task.  If p is nil, the current task is
  1468.     disabled.
  1469. */
  1470.  
  1471. void
  1472. SkelBackground (p)
  1473. vProcPtr    p;
  1474. {
  1475.     pBkgnd = p;
  1476. }
  1477.  
  1478.  
  1479. /*
  1480.     Return the current background task.  Return nil if none.
  1481. */
  1482.  
  1483. void
  1484. SkelGetBackground (p)
  1485. vProcPtr    *p;
  1486. {
  1487.     *p = pBkgnd;
  1488. }
  1489.  
  1490.  
  1491. /*
  1492.     Install an event-inspecting hook.  If p is nil, the hook is
  1493.     disabled.
  1494. */
  1495.  
  1496. void
  1497. SkelEventHook (p)
  1498. Boolean    (*p)();
  1499. {
  1500.     pEvent = p;
  1501. }
  1502.  
  1503.  
  1504. /*
  1505.     Return the current event-inspecting hook.  Return nil if none.
  1506. */
  1507.  
  1508. void
  1509. SkelGetEventHook (p)
  1510. Boolean    (**p)();
  1511. {
  1512.     *p = pEvent;
  1513. }
  1514.  
  1515.  
  1516. # ifdef    supportDialogs
  1517.  
  1518. /*
  1519.     Set the mask for event types that will be passed to dialogs.
  1520.     Bit 1 is always set, so that null events will be examined.
  1521.     (If this is not done, the caret does not blink in editText items.)
  1522. */
  1523.  
  1524. void
  1525. SkelDlogMask (mask)
  1526. Integer        mask;
  1527. {
  1528.     dlogEventMask = mask | 1;
  1529. }
  1530.  
  1531.  
  1532. /*
  1533.     Return the current dialog event mask.
  1534. */
  1535.  
  1536. void
  1537. SkelGetDlogMask (mask)
  1538. Integer        *mask;
  1539. {
  1540.     *mask = dlogEventMask;
  1541. }
  1542.  
  1543. # endif
  1544.